package org.p2psimulator.entity.protocol;

import org.p2psimulator.entity.Id;
import org.p2psimulator.entity.Message;
import org.p2psimulator.entity.Peer;
import org.p2psimulator.exceptions.ReputationRepositoryException;
import org.p2psimulator.engine.Environment;
import org.p2psimulator.util.Tuple;

/**
 * Representação de um protocolo de rede para o sistema.
 * Contém operações básicas:
 * 		1-  answareMessage= mecanismo de respota das mensagens do protocolo
 *      2 - joinCycle = ciclo de entrada na rede;
 *      3 - leaveCycle = ciclo de saída na rede;
 * Além dos ciclos básicos, um protocolo pode ter vários outros ciclos (votação,
 * estabilização, confirmação, avaliação, download, etc;) a depender da sua arquitetura.
 * A classe protocol deve prover um mecanismo de realização destes ciclos
 * em ordem. Ela possui 2 atributos, totalCycles e runningCycle. O primeiro
 * indica o total de ciclos de um determinado protocolo, o segundo, por sua vez,
 * indica qual ciclo está sendo atualmente executado. O método runCycle(int)
 * deve possibilitar que o simulador chame um ciclo específico passando o idenficador
 * apropriado. Para o simulador não é preciso saber qual ciclo está sendo executado em um
 * determinado instante, exceto pelos ciclos padrões de entrada
 * e saída na rede. Para os demais ele precisa apenas chamá-los em ordem. Isso é resolvido
 * fazendo com que o simulador chame os ciclos em ordem crescente de identificadores
 * runCycle(1), runCycle(2), runCycle(3)...
 * A implementação da ordem correta dos ciclos, assim como do método runCycle
 * depende de cada protocolo específico.
 * @author amorim
 *
 */
public abstract class Protocol {

    protected Environment env;
    protected int currentTransactionId;
    protected int totalCycles;
    protected int runningCycle = 0;
    protected int transactionResult = 0;

    public Protocol(Environment enviroment) {
        super();
        this.env = enviroment;
    }

    /**
     * Método abstrato para representar a respostas de mensagens.
     * Todo protocolo deve oferecer um mecanismo para resposta
     * de mensagens.
     * @param owner
     * @param msg
     */
    public abstract void answareMessage(Peer p, Message msg);

    public abstract void answareSpecificProtocolMessages(Peer peer, Message msg);

    public abstract String runCycle(int cycleId, Peer p);

    public abstract String joinNetworkRequestCycle(Peer p);

    public abstract String joinNetworkResponseCycle(Peer p);

    public abstract String leaveNetworkCycle(Peer p);

    public abstract int getLastTransactionResult();

    public void setTransactionResult(int transactionResult) {
        this.transactionResult = transactionResult;
    }

    public int getCurrentTransactioId() {
        return currentTransactionId;
    }

    public void setCurrentTransactioId(int currentTransactioId) {
        this.currentTransactionId = currentTransactioId;
    }

    public Environment getEnviroment() {
        return env;
    }

    public void setEnviroment(Environment enviroment) {
        this.env = enviroment;
    }

    public int getRunningCycle() {
        return runningCycle;
    }

    public void setRunningCycle(int runningCycle) {
        this.runningCycle = runningCycle;
    }

    public int getTotalCycles() {
        return totalCycles;
    }

    public void setTotalCycles(int totalCycles) {
        this.totalCycles = totalCycles;
    }
}
